//! 哈希表 HashMap
//和动态数组Vec一样，哈希表(HashMap)也是Rust内置的集合类型之一，同属std::collections模块下。
//
// 它提供了一个平均复杂度为O(1)的查询方法，是实现快速搜索必备的类型之一。


//HashMap的要求
//顾名思义, HashMap 要求一个可哈希（实现 Hash trait）的Key类型，和一个编译时知道大小的Value类型。
// 同时，Rust还要求你的Key类型必须是可比较的，在Rust中，你可以为你的类型轻易的加上编译器属性：
//#[derive(PartialEq, Eq, Hash)]
//这样，即可将你的类型转换成一个可以作为Hash的Key的类型。 但是，如果你想要自己实现Hash这个trait的话，你需要谨记两点：

//1.如果 Key1==Key2 ,那么一定有 Hash(Key1) == Hash(Key2)
//2.你的Hash函数本身不能改变你的Key值，否则将会引发一个逻辑错误（很难排查，遇到就完的那种）

use std::collections::HashMap;
//
#[test]
pub fn hash_map_demo(){
    let mut scores: HashMap<String, i32> = HashMap::new();
    scores.insert(String::from("hello"), 32);
    let value = scores.get("hell");
    let v = scores["hello"]; //不存在则panic
    println!("v = {}", v);
    match value {
        Option::Some(v) => println!("{}", v),
        Option::None => println!("未找到"),
    }
    //判断是否存在
    let b  = scores.contains_key("hello");
    //移除
    let o = scores.remove("hello");

    let teams = vec![String::from("Blue"), String::from("Yello")];
    let intial_scores = vec![10, 50];

    //通过vector创建HashMap
    let scores: HashMap<_,_> = teams.iter().zip(intial_scores.iter()).collect();
    //遍历
    for (k, v) in scores {
        println!("{}, {}", k, v);
    }

    let field_name = String::from("ok");
    let field_value = String::from("good");
    let mut map = HashMap::new();
    //String的所有的权会交给map,不能再使用field_name和field_value
    map.insert(field_name, field_value);

    //遍历
    for (k, v) in map {
        println!("{}, {}", k, v);
    }
    //println!("{}", field_name); //所有权发生转移，不能再使用了

    let mut m = HashMap::new();

    //使用引用，所有权不会转移
    let mut k1 = String::from("hh");
    let  v1 = String::from("kk");
    m.insert(&mut k1, &v1);
    for(k, v) in m {
        println!("{}, {}", k, v);
        *k = String::from("pl");
    }
    println!("{}, {}", k1, v1);
}

//entry
pub fn hash_map_demo2(){
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 20); //替换value


    //检查是否存在，返回一个枚举
    let e = scores.entry(String::from("Yello"));
    //不存在则插入59
    e.or_insert(59);

    //遍历
    for (k, v) in scores {
        println!("{}, {}", k, v);
    }

    //entry
    let text = "hello world wonderful world";
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        //返回 已存在的或插入的值的 可变引用
        let count = map.entry(word).or_insert(0);
        *count +=1; //将值加1
    }
    for (k, v) in map {
        println!("{}, {}", k, v);
    }
}